package com.shuma.upms.user.interceptor;

import com.shuma.upms.user.exception.AuthException;
import com.shuma.upms.user.util.JwtUtil;
import com.shuma.upms.user.util.UserContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 认证拦截器
 * 负责在Controller方法执行前，校验请求头中的JWT Token。
 */
@Slf4j
@Component
public class AuthInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtUtil jwtUtil;

    @Value("${app.jwt.token-header}")
    private String tokenHeader;

    @Value("${app.jwt.token-prefix}")
    private String tokenPrefix;

    /**
     * 在请求处理之前进行调用。
     * @return boolean - 返回true放行，抛出异常则被全局异常处理器捕获。
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws AuthException {

        // 1. 从请求头获取Authorization字段
        String authHeader = request.getHeader(tokenHeader);

        // 2. 校验Header是否存在及格式是否正确
        if (!StringUtils.hasText(authHeader) || !authHeader.startsWith(tokenPrefix)) {
            log.warn("认证失败：请求 {} 缺少或包含无效的 Authorization 请求头。", request.getRequestURI());
            throw new AuthException("认证失败，缺少有效的Token");
        }

        // 3. 提取Token字符串 (去除 "Bearer " 前缀)
        String token = authHeader.substring(tokenPrefix.length());

        try {
            // 4. 解析并校验Token
            Long userId = jwtUtil.extractUserId(token);
            String username = jwtUtil.extractUsername(token);

            if (userId == null || !jwtUtil.validateToken(token, username)) {
                throw new AuthException("Token无效或已过期");
            }

            // 5. 校验通过，将用户信息存入ThreadLocal，方便后续业务逻辑使用
            UserContextHolder.setUserId(userId);
            log.debug("用户认证成功！用户ID: {}, 正在访问: {}", userId, request.getRequestURI());

            return true; // 放行

        } catch (Exception e) {
            // 捕获所有JWT解析过程中的异常，统一包装成认证异常抛出
            log.error("JWT Token校验失败，请求URI: {}. 错误: {}", request.getRequestURI(), e.getMessage());
            throw new AuthException("Token无效或已过期");
        }
    }

    /**
     * 在整个请求处理完毕后调用，用于清理资源。
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        UserContextHolder.remove();
        log.debug("用户上下文已为请求 {} 清理完毕。", request.getRequestURI());
    }
}